﻿using System;
using System.IO;
using QingStor_SDK_NET.Yaml;

namespace QingStor_SDK_NET.Common
{
    /// loadMode: 
    public enum ConfigLoadMode
    {
        //json: Json Config String
        JsonStr = 1,
        //yaml: Yaml Config File Path
        YamlPath = 2
    }
    // Config Class
    public class CConfig
    {
        #region Properties
        public string Host { get; set; }
        public string Port { get; set; }
        public string Protocol { get; set; }
        public int ConnectionRetry { get; set; }
        public string LogLevel { get; set; }
        public string AccessKeyID { get; set; }
        public string SecretAccessKey { get; set; }
        public string UserAgent { get; set; }
        #endregion

        #region Utils
        /// <summary>
        /// 客户端标识(UserAgent)，示例："SepcifiedClient/1.1 (Universal)"
        /// </summary>
        /// <returns>客户端标识UA</returns>
        protected string GetUserAgent()
        {
            string osDesc = Environment.OSVersion.Platform + "; " + Environment.OSVersion.Version;
            return string.Format("{0}/{1} ({2}; {3})", QingStorCSharpSDK.ALIAS, QingStorCSharpSDK.VERSION, QingStorCSharpSDK.RTFX, osDesc);
        }

        /// <summary>
        /// 加载配置信息(载体Json文件)
        /// </summary>
        /// <param name="jsonStr">Config Info Load From Json</param>
        /// <returns></returns>
        protected bool LoadConfigInfoByJsonStr(string jsonStr)
        {
            if (string.IsNullOrEmpty(jsonStr))
                throw new ArgumentNullException("ConfigInfo Load from Json cannot be empty");
            var configInfo = CJsonUtils.JsonToObject<CConfig>(jsonStr);
            this.AccessKeyID = configInfo.AccessKeyID;
            this.SecretAccessKey = configInfo.SecretAccessKey;
            this.Host = string.IsNullOrEmpty(configInfo.Host) ? "qingstor.com" : configInfo.Host;
            this.Port = string.IsNullOrEmpty(configInfo.Port) ? "443" : configInfo.Port;
            this.Protocol = string.IsNullOrEmpty(configInfo.Protocol) ? "https" : configInfo.Protocol;
            this.ConnectionRetry = configInfo.ConnectionRetry <= 0 ? 3 : configInfo.ConnectionRetry;
            this.LogLevel = string.IsNullOrEmpty(configInfo.LogLevel) ? "warn" : configInfo.LogLevel;
            this.UserAgent = GetUserAgent();
            return !string.IsNullOrEmpty(AccessKeyID) && !string.IsNullOrEmpty(SecretAccessKey);
        }

        /// <summary>
        /// Load Config Info By Yaml File Path
        /// </summary>
        /// <param name="yamlConfigFilePath"></param>
        /// <returns></returns>
        protected bool LoadConfigInfoByYamlFilePath(string yamlConfigFilePath)
        {
            if (File.Exists(yamlConfigFilePath))
            {
                try
                {
                    YamlStream YamlStream = CYamlParser.Load(yamlConfigFilePath);
                    if (YamlStream != null)
                    {
                        foreach (YamlDocument YamlDoc in YamlStream.Documents)
                        {
                            DataItem Item = YamlDoc.Root;
                            if (Item is Mapping)
                            {
                                Mapping Mapping = Item as Mapping;
                                if (Mapping != null)
                                {
                                    foreach (MappingEntry MapEntry in Mapping.Enties)
                                    {
                                        string strKey = (MapEntry.Key == null ? "" : MapEntry.Key.ToString());
                                        string strValue = (MapEntry.Value == null ? "" : MapEntry.Value.ToString());

                                        // access_key_id
                                        if (strKey.Equals("access_key_id"))
                                        {
                                            this.AccessKeyID = strValue;
                                        }
                                        // secret_access_key
                                        else if (strKey.Equals("secret_access_key"))
                                        {
                                            this.SecretAccessKey = strValue;
                                        }
                                        // host
                                        else if (strKey.Equals("host"))
                                        {
                                            this.Host = strValue;
                                        }
                                        // port
                                        else if (strKey.Equals("port"))
                                        {
                                            this.Port = strValue;
                                        }
                                        // protocol
                                        else if (strKey.Equals("protocol"))
                                        {
                                            this.Protocol = strValue;
                                        }
                                        // connection_retries
                                        else if (strKey.Equals("connection_retries"))
                                        {
                                            this.ConnectionRetry = int.Parse(strValue);
                                        }
                                        // additional_user_agent
                                        else if (strKey.Equals("additional_user_agent"))
                                        {
                                            this.UserAgent = strValue;
                                        }
                                        // log_level
                                        else if (strKey.Equals("log_level"))
                                        {
                                            this.LogLevel = strValue;
                                        }
                                    }  // foreach (MappingEntry MapEntry in Mapping.Enties)

                                    return true;
                                }  // if (Mapping != null)
                            }  // if (Item is Mapping)
                        }  // foreach (YamlDocument YamlDoc in YamlStream.Documents)
                    }  // if (YamlStream != null)

                    return false;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
        #endregion


        #region Ctor
        public CConfig()
        {
        }

        public CConfig(string strAccessKeyID, string strSecretAccessKey)
        {
            this.AccessKeyID = strAccessKeyID;
            this.SecretAccessKey = strSecretAccessKey;
            this.Host = "qingstor.com";
            this.Port = "443";
            this.Protocol = "https";
            this.ConnectionRetry = 3;
            this.LogLevel = "warn";
            this.UserAgent = GetUserAgent();
        }

        /// <summary>
        /// 按加载方式传入配置信息
        /// loadMode: 
        ///     json: Json Config String
        ///     yaml: Yaml Config File Path
        /// </summary>
        /// <param name="strYamlPathorJsonStr"></param>
        /// <param name="loadMode"></param>
        public CConfig(string strYamlPathorJsonStr, ConfigLoadMode loadMode = ConfigLoadMode.JsonStr)
        {
            bool loadDefault = false;
            if(loadMode == ConfigLoadMode.JsonStr)
            {
                if (!LoadConfigInfoByJsonStr(strYamlPathorJsonStr))
                    loadDefault = true;
            } else if(!LoadConfigInfoByYamlFilePath(strYamlPathorJsonStr)) {
                loadDefault = true;
            }

            if (loadDefault)
            {
                this.AccessKeyID = "ACCESS_KEY_ID";
                this.SecretAccessKey = "SECRET_ACCESS_KEY";
                this.Host = "qingstor.com";
                this.Port = "443";
                this.Protocol = "https";
                this.ConnectionRetry = 3;
                this.LogLevel = "warn";
                this.UserAgent = "";
            }
        }

        ~CConfig()
        { 
        }
        #endregion

    }
}
